package com.skj.client ;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.http.client.* ;
import com.google.gwt.json.client.* ;
import com.google.gwt.jsonp.client.* ;
import com.google.gwt.user.client.* 		 ;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.* 		 ;

public class Engine 
{
	JSONObject	doc ;		// Document - Root Object of SKJ Framework
	JSONArray	docObjects ;
	
	JSONArray	slides ;
	JSONArray	layers ;
	
	JSONObject cSlide ;
	
	private Element	eCanvas	;
	private Canvas canvas ;
	
	private LocalStorage localStorage ;
	
	Timer timer ;
	
	private int maxX ;
	private int maxY ;
	
	public Engine(int width, int height)
	{
		docObjects	= new JSONArray() ;
		slides		= new JSONArray() ;
		layers		= new JSONArray() ;
		
		maxX = width ;
		maxY = height ;
		
		// INITIALIZING CANVAS
		canvas = new Canvas(maxX,maxY, this) ;
		
		// INITIALIZING TIMER
		timer = new Timer()
		{
			@Override
			public void run()
			{
				outputTimer_Tick() ;
			}
		};
		
		timer.scheduleRepeating(1000) ;
	}

	// ENGINE MANAGEMENT
	public void load(String json)
	{
		//System.out.println(json) ;
		//JSONValue jsonValue = JSONParser.parse(json) ;
		//doc = jsonValue.isObject() ;
		
		//JSONString cSlideName = slides.get(0).isString() ;
		//cSlide = doc.get(cSlideName.stringValue()).isObject() ;
		
		//if(cSlide != null)
		//{
			//run() ;
		//}
	}
	
	public void run()
	{
		runSlide() ;
	}
	
	public void runSlide()
	{
		JSONArray slideLayers = cSlide.get("LAYERS").isArray() ;
		
		for(int i = 0; i < slideLayers.size(); i++)
		{
			JSONObject cLayer = doc.get(slideLayers.get(i).isString().stringValue()).isObject() ;
			runLayer(cLayer) ;
		}
	}
	
	public void runLayer(JSONObject layer)
	{
		String style 		= getStrInput(layer, "STYLE") ;
		double x			= getNumInput(layer, "X") ;
		double y			= getNumInput(layer, "Y") ;
		double width		= getNumInput(layer, "WIDTH") ;
		double height		= getNumInput(layer, "HEIGHT") ;
		JavaScriptObject source = getObjectInput(layer, "SOURCE") ;
		double [] styleData = getNumArrayInput(layer, "STYLE_DATA") ;
		double [] effectData= getNumArrayInput(layer, "EFFECT_DATA") ;
		
		if(style.compareTo("FORMATTED_TEXT") == 0)
		{
			//	DATA : FONT, ALIGNMENT, BASELINE, DRAW_STYLE
		}
		else if(style.compareTo("LINE") == 0)
		{
			canvas.drawLine(x, y, x + width, y + height) ;
		}
		else if(style.compareTo("PATH") == 0)
		{
			
		}
		else if(style.compareTo("RECTANGLE") == 0)
		{	
			if(styleData != null)
			{
				boolean color = true ;
				double r = styleData[0] ;
				double g = styleData[1] ;
				double b = styleData[2] ;
				
				canvas.drawRect(x, y, width, height, color, r, g, b) ;
			}
			else
			{
				canvas.drawRect(x, y, width, height, false, 0, 0, 0) ;
			}
		}
		else if(style.compareTo("FILLED_RECTANGLE") == 0)
		{
			if(styleData != null)
			{
				boolean color = true ;
				double r = styleData[0] ;
				double g = styleData[1] ;
				double b = styleData[2] ;
				
				canvas.fillRect(x, y, width, height, color, r, g, b) ;
			}
			else
			{
				canvas.fillRect(x, y, width, height, false, 0, 0, 0) ;
			}
		}
		else if(style.compareTo("ROUNDED_RECTANGLE") == 0)
		{
			double arcWidth = styleData[0] ;
			double arcHeight= styleData[1] ;
			
			canvas.fillRoundRect(x, y, width, height, arcWidth, arcHeight) ;
		}
		else if(style.compareTo("ROUNDED_FILLED_RECTANGLE") == 0)
		{
			double arcWidth = styleData[0] ;
			double arcHeight= styleData[1] ;
			
			canvas.fillRoundRect(x, y, width, height, arcWidth, arcHeight) ;
		}
		else if(style.compareTo("ARC") == 0)
		{
			double startAngle 	= styleData[0] ;
			double endAngle 	= styleData[1] ;
			double anticlockwise= styleData[2] ;
			
			canvas.arc(x, y, width/2, startAngle, endAngle, anticlockwise) ;
		}
		else if(style.compareTo("QUADRATIC_CURVE") == 0)
		{
			double cpx = styleData[0] ;
			double cpy = styleData[1] ;
			
			canvas.quadraticCurveTo(cpx, cpy, x, y) ;
		}
		else if(style.compareTo("BEZIER_CURVE") == 0)
		{
			double cp1x = styleData[0] ;
			double cp1y = styleData[1] ;
			double cp2x = styleData[2] ;
			double cp2y = styleData[3] ;
			
			canvas.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) ;
		}
		else if(style.compareTo("IMAGE") == 0)
		{	
			canvas.drawImage(source, x, y) ;
		}
		else if(style.compareTo("IMAGE_FRAME") == 0)
		{
			canvas.drawImage(source, 0,0, width, height, x, y, width, height) ;
		}
		else if(style.compareTo("ANIMATION") == 0)
		{
			
		}
		else if(style.compareTo("VIDEO") == 0)
		{
			
		}
		else if(style.compareTo("AUDIO_PLAYER") == 0)
		{
			
		}
		else if(style.compareTo("CHART") == 0)
		{
			
		}
		else if(style.compareTo("MAP") == 0)
		{
			
		}
		// GWT WIDGETS
		else if(style.compareTo("BUTTON") == 0)
		{
			
		}
		else if(style.compareTo("CHECK_BOX") == 0)
		{
			
		}
		else if(style.compareTo("DIALOG_BOX") == 0)
		{
			
		}
		else if(style.compareTo("FILE_UPLOAD") == 0)
		{
			
		}
		else if(style.compareTo("TABLE") == 0)
		{
			
		}
		else if(style.compareTo("FRAME") == 0)
		{
		}
		else if(style.compareTo("LABEL") == 0)
		{
		}
		else if(style.compareTo("LIST_BOX") == 0)
		{
		}
		else if(style.compareTo("TEXT_BOX") == 0)
		{
		}
		else if(style.compareTo("PASSWORD_TEXT_BOX") == 0)
		{
		}
		else if(style.compareTo("RICH_TEXT_BOX") == 0)
		{
		}
		else if(style.compareTo("RADIO_BUTTON") == 0)
		{
		}
		else if(style.compareTo("SUGGEST_BOX") == 0)
		{
		}
		else if(style.compareTo("TREE") == 0)
		{
		}
	}
	
	// ENGINE OUTPUTS
	public void outputEnable()
	{
		
	}
	
	public void outputDisable()
	{
		
	}
	
	public void outputEnter(int source, int x, int y)
	{
		
	}
	
	public void outputExit(int source, int x, int y)
	{
		
	}
	
	public void outputMove(int source, int x, int y)
	{
		
	}
	
	public void outputPress(int source, int x, int y)
	{
		//System.out.println("Press " + source + " " + x + " " + y) ;
	}
	
	public void outputRelease(int source, int x, int y)
	{
		
	}
	
	public void outputClick(int source, int x, int y)
	{
		
	}
	
	public void outputDouble_Click(int source, int x, int y)
	{
		
	}
	
	public void outputTimer_Tick()
	{
		
	}
	
	// METHODS FOR CREATING OBJECTS
	
	// CREATING DATA
	public void CREATE_NUMBER(String name, double value)
	{
		docObjects.set(docObjects.size() - 1, new JSONString(name)) ;
		doc.put(name, new JSONNumber(value)) ;
	}
	
	public void CREATE_TEXT(String name, String text)
	{
		docObjects.set(docObjects.size() - 1, new JSONString(name)) ;
		doc.put(name, new JSONString(text)) ;
	}
	
	public void CREATE_DATE(String name, double dd, double mm, double yyyy, double hh, double mi, double ss)
	{
		JSONObject date = new JSONObject() ;
		date.put("TYPE"	 , new JSONString("DATE")) ;
		
		date.put("DATE"	 , new JSONNumber(dd)) ;
		date.put("MONTH" , new JSONNumber(mm)) ;
		date.put("YEAR"	 , new JSONNumber(yyyy)) ;
		date.put("HOUR"	 , new JSONNumber(hh)) ;
		date.put("MINUTE", new JSONNumber(mi)) ;
		date.put("SECOND", new JSONNumber(ss)) ;
		
		addObject(name, date) ;
	}
	
	public void CREATE_RESOURCE(String name, String URL, String mimeType)
	{
		JSONObject res = new JSONObject() ;
		res.put("TYPE"	, new JSONString("RESOURCE")) ;
		
		res.put("URL"	, new JSONString(URL)) ;
		res.put("MIME" , new JSONString(mimeType)) ;
		
		addObject(name, res) ;
	}
	
	public void CREATE_USER(String name, String ID, String firstName, String lastName, String primaryEmail)
	{
		JSONObject user = new JSONObject() ;
		user.put("TYPE"	, new JSONString("USER")) ;
		
		user.put("ID"			, new JSONString(ID)) ;
		user.put("FIRST_NAME" 	, new JSONString(firstName)) ;
		user.put("LAST_NAME" 	, new JSONString(lastName)) ;
		user.put("EMAIL1" 		, new JSONString(primaryEmail)) ;
		
		addObject(name, user) ;
	}
	
	public void CREATE_LOCALE(String name, String lang, String script, String region, String variant)
	{
		JSONObject locale = new JSONObject() ;
		locale.put("TYPE" , new JSONString("LOCALE")) ;
		
		locale.put("LANGUAGE" , new JSONString(lang)) ;
		locale.put("SCRIPT"   , new JSONString(script)) ;
		locale.put("REGION"   , new JSONString(region)) ;
		locale.put("VARIANT"  , new JSONString(variant)) ;
		
		addObject(name, locale) ;
	}
	
	public void CREATE_URL(String name, String URL)
	{
		JSONObject url = new JSONObject() ;
		url.put("TYPE" , new JSONString("URL")) ;
		
		url.put("URL"	, new JSONString(URL)) ;
		
		addObject(name, url) ;
	}
	
	public void CREATE_MATH(String name, double op, double val1, double val2)
	{
		JSONObject math = new JSONObject() ;
		math.put("TYPE" , new JSONString("MATH")) ;
		
		//  1 - PLUS
		//  2 - MINUS
		//  3 - MULTIPLY
		//  4 - DIVIDE
		//  5 - MOD
		//  6 - SQUARE ROOT
		//  7 - POWER
		//  8 - SIN
		//  9 - COS
		// 10 - TAN
		// 11 - ASIN
		// 12 - ACOS
		// 13 - ATAN
		// 14 - ROUND
		// 15 - ABSOLUTE
		// 16 - RANDOM
		// 17 - MIN
		// 18 - MAX
		// 19 - E
		// 20 - PI
		// 21 - EXP
		// 22 - LOG
		math.put("OPERATION"	, new JSONNumber(op)) ;
		math.put("VALUE1"		, new JSONNumber(val1)) ;
		math.put("VALUE2"		, new JSONNumber(val2)) ;
		
		addObject(name, math) ;
	}
	
	public void CREATE_HTML(String name, String html)
	{
		JSONObject htmlCode = new JSONObject() ;
		htmlCode.put("TYPE" , new JSONString("HTML")) ;
		
		htmlCode.put("HTML"	, new JSONString(html)) ;
		
		addObject(name, htmlCode) ;
	}
	
	// CREATING CONDITIONS
	public void CREATE_CONDITION_LOGICAL()
	{
		
	}
	
	public void CREATE_CONDITION_COLLISION()
	{
		
	}
	
	// CREATING ACTIONS
	public void CREATE_ACTION_EQUAL_TO()
	{
		
	}
	
	public void CREATE_ACTION_CLOSE_DOC()
	{
		
	}
	
	public void CREATE_ACTION_LOG()
	{
		
	}
	
	// CREATING GROUPS
	public void CREATE_SLIDE(String name, 
							 double visible, double state, double subState,
							 double x, double y, double width, double height,
							 double timerInterval, String [] layerNames)
	{
		JSONObject slide = new JSONObject() ;
		slide.put("TYPE" , new JSONString("SLIDE")) ;
		
		slide.put("VISIBLE"	 , new JSONNumber(visible)) ;
		slide.put("STATE"	 , new JSONNumber(state)) ;
		slide.put("SUB_STATE", new JSONNumber(subState)) ;
		slide.put("X"		 , new JSONNumber(x)) ;
		slide.put("Y"		 , new JSONNumber(y)) ;
		slide.put("WIDTH"	 , new JSONNumber(width)) ;
		slide.put("HEIGHT"	 , new JSONNumber(height)) ;
		slide.put("TIMER_INTERVAL", new JSONNumber(timerInterval)) ;
		
		JSONArray layers = new JSONArray() ;
		for(int i = 0; i < layerNames.length;i++)
		{
			layers.set(i, new JSONString(layerNames[i])) ;
		}
		slide.put("LAYERS"	, layers) ;
		
		slides.set(slides.size(), new JSONString(name)) ;
		addObject(name, slide) ;
	}
	
	public void CREATE_LAYER(String name,
							 String style, 
							 double visible, double state, double subState,
							 double x, double y, double width, double height,
							 String source, double [] styleData, double [] effectData)
	{
		JSONObject layer = new JSONObject() ;
		layer.put("TYPE" , new JSONString("LAYER")) ;
		
		// STYLES
		//	FORMATTED TEXT
		//		DATA : FONT, ALIGNMENT, BASELINE, DRAW_STYLE
		// 	LINE
		//	PATH
		//	RECTANGLE
		//	FILLED RECTANGLE
		//	ROUNDED RECTANGLE
		//	ROUNDED FILLED RECTANGLE
		// 	ARC
		//	QUADRATIC_CURVE
		//	BEZIER_CURVE
		// 	IMAGE
		// 	IMAGE FRAME
		// 	ANIMATION
		//	VIDEO
		// 	AUDIO_PLAYER
		//	CHART
		
		//	BUTTON -
		//	CHECK_BOX -
		//	DIALOG_BOX -
		//	FILE_UPLOAD
		//	TABLE
		//	FRAME -
		//	LABEL -
		//	LIST_BOX -
		//	TEXT_BOX -
		//	PASSWORD_TEXT_BOX
		//	RICH_TEXT_BOX -
		//	RADIO_BUTTON -
		//	SUGGEST_BOX
		//	TREE -
		
		layer.put("STYLE" , new JSONString(style)) ;
		
		layer.put("VISIBLE"	 , new JSONNumber(visible)) ;
		layer.put("STATE"	 , new JSONNumber(state)) ;
		layer.put("SUB_STATE", new JSONNumber(subState)) ;
		layer.put("X"		 , new JSONNumber(x)) ;
		layer.put("Y"		 , new JSONNumber(y)) ;
		layer.put("WIDTH"	 , new JSONNumber(width)) ;
		layer.put("HEIGHT"	 , new JSONNumber(height)) ;
		
		if(source != null)
		{
			JavaScriptObject obj ;
			
			if(style.compareTo("IMAGE") == 0 || style.compareTo("IMAGE_FRAME") == 0)
			{
				obj = canvas.createImage(source) ;
				layer.put("SOURCE"	 , new JSONObject(obj)) ;
			}
		}
	
		// STYLE_DATA
		if(styleData != null)
		{
			JSONArray styleDATA = new JSONArray() ;
			for(int i = 0; i < styleData.length;i++)
			{
				styleDATA.set(i, new JSONNumber(styleData[i])) ;
			}
			layer.put("STYLE_DATA"	, styleDATA) ;
		}
		
		// EFFECT_DATA
		if(effectData != null)
		{
			JSONArray effectDATA = new JSONArray() ;
			for(int i = 0; i < effectData.length;i++)
			{
				effectDATA.set(i, new JSONNumber(effectData[i])) ;
			}
			layer.put("EFFECT_DATA"	, effectDATA) ;
		}
		
		layers.set(layers.size(), new JSONString(name)) ;
		addObject(name, layer) ;
	}
	
	public void addObject(String name, JSONObject object)
	{
		docObjects.set(docObjects.size(), new JSONString(name)) ;
		doc.put(name, object) ;
	}
	
	public void GET_OBJECT()
	{
		
	}
	
	public double getNumInput(JSONObject object, String input)
	{
		return object.get(input).isNumber().doubleValue() ;
	}
	
	public double [] getNumArrayInput(JSONObject object, String input)
	{		
		JSONValue val = object.get(input) ;
		
		if(val != null)
		{
			JSONArray array = val.isArray() ;
			int arraySize = array.size() ;
			
			double [] values = new double[arraySize] ;
			
			for(int i = 0; i < arraySize;i++)
			{
				values[i] = array.get(i).isNumber().doubleValue() ;
			}
			
			return values ;
		}
	
		return null ;
	}
	
	public String getStrInput(JSONObject object, String input)
	{
		return object.get(input).isString().stringValue() ;
	}
	
	public JavaScriptObject getObjectInput(JSONObject object, String input)
	{
		JSONValue val = object.get(input) ;
		
		if(val != null)
		{
			return val.isObject().getJavaScriptObject() ;
		}
		else
		{
			return null ;
		}
	}
	
	public void UPDATE_OBJECT()
	{
		
	}
	
	public void DELETE_OBJECT()
	{
		
	}
	
	public native void getJSONFromServer(String URL)
	/*-{
			
       			var head	= $doc.getElementsByTagName('head')[0];
				var script	= $doc.createElement('script');
				script.type	= 'application/javascript';
				script.src	= 'http://www.skjworld.com/editor/json.js' ;
				head.appendChild(script);
       			//processData() ;
	}-*/;
	
}